import { any } from "../core/logic";
import { Engine } from "../Engine";
import { Geometry } from "./Geometry";
import { process } from "../process/worker/process";
/**
 * 点状几何体。
 * @class
 * @memberof w.geometry
 */
class PointGeometry extends Geometry {
    /**
     * 创建材质
     * @constructor
     * @param {*} opts
     * @param {string} opts.name 【可选】名称。
     */
    constructor(opts = {}, share) {
        let rawPosition = any(opts.position, new Float32Array([]));
        delete opts.position
        super({ autoUpdate: false });
        this.type = "PointGeometry";
        this.geometryType = "PointGeometry";
        this.shape = any(opts.shape, 'rect');
        this._hash = "";
        // this.position = opts.position;
        this.rawPosition = rawPosition;
        this.rawColor = any(opts.color, new Float32Array([]));
        this.varySize = any(opts.varySize, false);
        this.pixelUnit = any(opts.pixelUnit, true);
        let camera = Engine.instance.scene.getCamera();
        let cameraDistance = camera.trans.position.distanceTo(camera.at)
        this.pixelRatio = cameraDistance * 2.309401076758503 / camera.size[1];
        this.size = any(opts.size, [300, 300]);
        this.horizontalLocation = any(opts.horizontalLocation, 'center');
        this.verticalLocation = any(opts.verticalLocation, 'middle');
        this.locationOffset = [0, 0];
        this.relativeShift = any(opts.relativeShift, [0, 0]);
        this.calcData = opts.calcData;
        this.processCallback = any(opts.callback, () => { })
        this.fillPosition();
    }
    set pixelUnit(v) {
        if (this.pixelUnit !== v) {
            this._pixelUnit = v;
            this.addConfigParam("pixelUnit", v);
            this.update();
        }
        return this;
    }
    get pixelUnit() {
        return this._pixelUnit;
    }
    set varySize(v) {
        this._varySize = v;
        this.addConfigParam("pointSizeVarying", v);
        return this;
    }
    get varySize() {
        return this._varySize;
    }
    set size(v) {
        if (v != this.size && v) {
            this._size = v;
            this.fillPosition();
            this.addParam("pointSize");
            return this;
        }

    }
    get size() {
        return this._size;
    }
    set horizontalLocation(v) {
        this._horizontalLocation = v;
        return this;
    }
    get horizontalLocation() {
        return this._horizontalLocation;
    }
    set verticalLocation(v) {
        this._verticalLocation = v;
        return this;
    }
    get verticalLocation() {
        return this._verticalLocation;
    }
    set pointNormal(v) {
        this._pointNormal = v;
        this.addParam("pointNormal");
        return this;
    }
    get pointNormal() {
        return this._pointNormal;
    }
    set relativeShift(v) {
        if (!v) {
            v = [this.locationOffset[0], this.locationOffset[1]];
        } else {
            v = [v[0] + this.locationOffset[0], v[1] + this.locationOffset[1]];
        }
        this._relativeShift = v;
        this.addParam("relativeShift");
        return this;
    }
    get relativeShift() {
        return this._relativeShift;
    }
    set locationOffset(v) {
        this._locationOffset = v;
        if (this.relativeShift) {
            this.relativeShift = this.relativeShift;
        }

        return this;
    }
    get locationOffset() {
        return this._locationOffset;
    }
    getPoints() {
        let noRepeatPoints = [];
        for (var j = 0; j < this.rawPosition.length; j += 3) {
            if (!(noRepeatPoints[noRepeatPoints.length - 1] && this.comparePoint(noRepeatPoints[noRepeatPoints.length - 1], [this.rawPosition[j], this.rawPosition[j + 1], this.rawPosition[j + 2]]))) {
                noRepeatPoints.push([this.rawPosition[j], this.rawPosition[j + 1], this.rawPosition[j + 2]])
            }
        }
        return noRepeatPoints;
    }
    fillPosition() {
        let points = this.getPoints();
        this.noRepeatPoints = points;
        if (this.calcData) {
            let {
                positions,
                indices_array,
                directions,
                uvs,
                colors,
                locationOffset
            } = this.calcData;
            this.autoUpdate = false;
            this.indices = indices_array;
            this.position = positions;
            this.locationOffset = locationOffset;
            this.pointNormal = directions;
            this.texCood0 = uvs;
            if (colors.length) {
                this.color = colors;
            }
            this.autoUpdate = true;
            this.update();
            this.processCallback(this.calcData);
        } else {
            process({
                type: "point",
                back: this.back,
                points,
                color: this.rawColor,
                size: this.size,
                horizontalLocation: this.horizontalLocation,
                verticalLocation: this.verticalLocation,
                shape: this.shape
            }, (message) => {
                let {
                    positions,
                    indices_array,
                    directions,
                    uvs,
                    colors,
                    locationOffset
                } = message.data;
                this.autoUpdate = false;
                this.indices = indices_array;
                this.position = positions;
                this.locationOffset = locationOffset;
                this.pointNormal = directions;
                this.texCood0 = uvs;
                if (colors.length) {
                    //     let ColorCom = this.get('Color');
                    //     ColorCom.size = 0;
                    this.color = colors;
                }
                this.autoUpdate = true;
                this.update();
                this.processCallback(message.data);
            })
        }

    }
    comparePoint(a, b) {
        if (!a || !b) return false;
        return (
            a[0] === b[0] &&
            a[1] === b[1] &&
            a[2] === b[2]
        )
    }
    toGPU() {
        if (this.has("pointSize")) {
            let data = [...this.size];
            if (this.varySize) {
                data = data.map(item => item * this.pixelRatio);
            }
            this.bufferToGPU(new Float32Array(data), 'pointSize', GPUShaderStage.VERTEX);
        }
        if (this.has("pointNormal")) {
            this.initVertex(this.pointNormal, "pointNormal", 3);
        }
        if (this.has("relativeShift")) {
            let data = [...this.relativeShift];
            if (this.varySize) {
                data = data.map(item => item * this.pixelRatio);
            }
            this.bufferToGPU(new Float32Array(data), 'relativeShift', GPUShaderStage.VERTEX);
        }
        super.toGPU();
    }




}

export { PointGeometry };
